#include "../../common/etcd.hpp"
#include <gflags/gflags.h>
#include "../../common/channel.hpp"
#include "main.pb.h"
#include <thread>

DEFINE_bool(run_mode, false, "程序运行模式， false调试; true发布;");
DEFINE_string(log_file, "", "发布模式下，用于指定日志的输出文件");
DEFINE_int32(log_level, 0, "发布模式下，用于指定日志的输出等级");

DEFINE_string(etcd_host, "http://127.0.0.1:2379", "服务注册中心地址");
DEFINE_string(base_service, "/service", "服务监控根目录");
DEFINE_string(call_service, "/service/echo", "服务目录");

// void online(const std::string &service_name, const std::string &service_host) {
//     LOG_DEBUG("上线服务: {}-{}", service_name, service_host);
// }

// void offline(const std::string &service_name, const std::string &service_host) {
//     LOG_DEBUG("上线服务: {}-{}", service_name, service_host);
// }

int main(int argc, char *argv[])
{

    google::ParseCommandLineFlags(&argc, &argv, true);

    init_logger(FLAGS_run_mode, FLAGS_log_file, FLAGS_log_level);

    // 1. 构造rpc信道管理对象
    auto sm = std::make_shared<bite_im::ServiceManager>();
    //服务发现的核心目标是 “找到‘某类服务’的所有可用节点，再选择一个节点发起调用”，
    //不需要关心 “具体是哪个实例”，因此用 服务基类标识（/service/echo）：
    sm->declared(FLAGS_call_service);
    auto put_cb = std::bind(&bite_im::ServiceManager::onServiceOnline, sm.get(), std::placeholders::_1, std::placeholders::_2);
    auto del_cb = std::bind(&bite_im::ServiceManager::onServiceOffline, sm.get(), std::placeholders::_1, std::placeholders::_2);
    // 2.构造服务发现对象
    Discovery::ptr rclient = std::make_shared<Discovery>(FLAGS_etcd_host, FLAGS_base_service, put_cb, del_cb);

    while (1)
    {

        // 3. 通过Rpc信道管理对象，获取提供Echo服务的信道
        auto channel = sm->choose(FLAGS_call_service);
        if (!channel)
        {
            std::this_thread::sleep_for(std::chrono::seconds(1));
            continue;
        }
        // 4. 发起EchoRpc调用
        example::EchoService_Stub stub(channel.get());
        // 构造请求消息
        example::EchoRequest req;
        req.set_message("hello~world~！");
        // 异步调用Echo方法
        brpc::Controller *cntl = new brpc::Controller();          // 控制调用过程（如超时,错误）
        example::EchoResponse *rsp = new example::EchoResponse(); // 接收响应

        stub.Echo(cntl, &req, rsp, nullptr); // 同步调用
        if (cntl->Failed())
        {
            std::cout << "Rpc调用失败：" << cntl->ErrorText() << std::endl;
            delete cntl;
            delete rsp;
            std::this_thread::sleep_for(std::chrono::seconds(1));
            continue;
        }
        std::cout << "收到响应: " << rsp->message() << std::endl;
        std::this_thread::sleep_for(std::chrono::seconds(1));
    }

    // std::this_thread::sleep_for(std::chrono::seconds(600));
    return 0;
}
